package edu.rmit.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import edu.rmit.contant.RoleType;
import edu.rmit.contant.TableConstant;
import edu.rmit.dao.IUserDAO;
import edu.rmit.domain.User;
import edu.rmit.util.DBManager;

/**
 * This class implements the user operation. Like get user, change the user
 * status, register user, and get user by its status.
 * 
 * @author Joey George
 * @version 1.0
 */
public class UserDAOImpl implements IUserDAO {

	/**
	 * The database connection management class.
	 */
	private DBManager dbManager = null;

	/**
	 * The constructor without parameter to initialize a database connection.
	 */
	public UserDAOImpl() {
		dbManager = new DBManager();
	}

	/**
	 * This method implements the operation to get an user by its user name.
	 * 
	 * @param userName
	 *            The user name of particular user.
	 * @return The user object which represented by the user name.
	 */
	public User getUserInfo(String userName) {
		String sqlString = "select * from " + TableConstant.USER_INFO_TABLE
				+ " where username = ? ";

		Connection connection = dbManager.getConnection();
		PreparedStatement preparedState = null;
		ResultSet resultSet = null;

		try {
			preparedState = connection.prepareStatement(sqlString);
			preparedState.setString(1, userName);
			resultSet = preparedState.executeQuery();
			if (resultSet != null && resultSet.next()) {
				User userInfo = new User();
				userInfo.setId(resultSet.getInt("id"));
				userInfo.setUserName(resultSet.getString("username"));
				userInfo.setPassWord(resultSet.getString("password"));
				userInfo.setFirstName(resultSet.getString("firstname"));
				userInfo.setLastName(resultSet.getString("lastname"));
				userInfo.setRoleType(resultSet.getInt("roletype"));
				userInfo.setActive(resultSet.getBoolean("isactive"));
				userInfo.setIslogin(resultSet.getBoolean("islogin"));
				return userInfo;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dbManager.closeAll(resultSet, preparedState, connection);
		}
		return null;
	}

	/**
	 * This method implements the operation to change an user's boolean status.
	 * 
	 * @param userName
	 *            The user name of which you want to changed.
	 * @param destinationStatus
	 *            The destination status which you want to changed to.
	 */
	@Override
	public void changeLoginStatus(String userName, boolean destinationStatus) {
		String changeValueSQL = "update " + TableConstant.USER_INFO_TABLE
				+ " set islogin = ? where username = ?";
		changestatus(changeValueSQL, userName, destinationStatus);
	}
	
	/**
	 * This method implements the operation to change an user's status.
	 * 
	 * @param userName
	 *            The user name of which you want to changed.
	 * @param destinationStatus
	 *            The destination status which you want to changed to.
	 */
	@Override
	public void changeActiveStatus(String userName, boolean destinationStatus) {
		String changeValueSQL = "update " + TableConstant.USER_INFO_TABLE
				+ " set isactive = ? where username = ?";
		changestatus(changeValueSQL, userName, destinationStatus);
	}

	/**
	 * This method implements to create a new account for a user
	 * 
	 * @param userName
	 *            The user name which you can use to login.
	 * @param password
	 *            The password which you can use this to login.
	 * @param firstName
	 *            The first name of the user.
	 * @param lastName
	 *            The last name of the user.
	 * @param isActive
	 *            The status of the user.
	 * @return A particular which contains this attribute.
	 */
	@Override
	public void createAccount(String userName, String password,
			String firstName, String lastName, boolean isActive) {
		String sqlString = "insert into "
				+ TableConstant.USER_INFO_TABLE
				+ "(id,username,password,firstname,lastname,isactive,roletype,islogin)"
				+ " values(" + TableConstant.SEQ_USER_INFO + ",?,?,?,?,?,?,?)";

		Connection connection = dbManager.getConnection();
		PreparedStatement preparedState = null;

		try {
			preparedState = connection.prepareStatement(sqlString);
			preparedState.setString(1, userName);
			preparedState.setString(2, password);
			preparedState.setString(3, firstName);
			preparedState.setString(4, lastName);
			preparedState.setBoolean(5, isActive);
			preparedState.setInt(6, RoleType.USER);
			preparedState.setBoolean(7, false);
			preparedState.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dbManager.closeAll(null, preparedState, connection);
		}
	}

	/**
	 * This method implements the operation to get the users by its status.
	 * 
	 * @param isActive
	 *            The destination status which you want to get.
	 * @return A list of users which status is currently in this status.
	 */
	@Override
	public List<User> getUsersByActiveStatus(boolean isActive) {

		String sqlString = "select * from " + TableConstant.USER_INFO_TABLE
				+ " where isactive = ?";

		Connection connection = dbManager.getConnection();
		PreparedStatement preparedState = null;
		ResultSet resultSet = null;

		List<User> matchedUsers = new ArrayList<User>();
		try {
			preparedState = connection.prepareStatement(sqlString);

			preparedState.setBoolean(1, isActive);
			resultSet = preparedState.executeQuery();
			while (resultSet != null && resultSet.next()) {
				User userInfo = new User();
				userInfo.setId(resultSet.getInt("id"));
				userInfo.setUserName(resultSet.getString("username"));
				userInfo.setPassWord(resultSet.getString("password"));
				userInfo.setFirstName(resultSet.getString("firstname"));
				userInfo.setLastName(resultSet.getString("lastname"));
				userInfo.setRoleType(resultSet.getInt("roletype"));
				userInfo.setActive(resultSet.getBoolean("isactive"));
				matchedUsers.add(userInfo);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dbManager.closeAll(resultSet, preparedState, connection);
		}
		return matchedUsers;
	}
	
	/**
	 * 
	 * @param changeValueSQL
	 *            The SQL script which you want to run.
	 * @param userName
	 *            The user name of which you want to changed.
	 * @param destinationStatus
	 *            The destination status which you want to changed to.
	 */
	private void changestatus(String changeValueSQL, String userName,
			boolean destinationStatus) {
		Connection connection = dbManager.getConnection();
		PreparedStatement preparedState = null;
		try {
			preparedState = connection.prepareStatement(changeValueSQL);
			preparedState.setBoolean(1, destinationStatus);
			preparedState.setString(2, userName);
			preparedState.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			dbManager.closeAll(null, preparedState, connection);
		}
	}
}
